package db

import (
	"errors"
	"hr/api/dto"

	"github.com/spf13/cast"
	"gorm.io/gorm"
)

// WorkOvertimeApproval 加班申请
type WorkOvertimeApproval struct {
	AppModel
	UserID           string `gorm:"size:64" json:"user_id"`
	WorkOvertimeTime string `gorm:"size:64" json:"work_overtime_time"`
	Duration         string `gorm:"size:64" json:"duration"`
	Reason           string `json:"reason"`
	CreateBy         string `gorm:"size:128" json:"createBy"`        // 创建人
	UpdateBy         string `gorm:"size:128" json:"updateBy"`        // 更新人
	Remark           string `gorm:"size:255" json:"remark"`          //备注
	OrderStatus      string `gorm:"size:64;" json:"order_status"`    // 申请状态 1保存、2提交
	ApprovalStatus   string `gorm:"size:64;" json:"approval_status"` // 是否同意 1是2否
	RefuseReason     string `json:"refuseReason"`
}

func (u *WorkOvertimeApproval) TableName() string {
	return "approval_work_overtime"
}

type WorkOvertimeApprovalName struct {
	WorkOvertimeApproval
	UserName string `json:"user_name"`
}

type WorkOvertimeApprovalPageModel struct {
	Total    int64                      `json:"total"`
	Result   []WorkOvertimeApprovalName `json:"result"`
	PageNo   int                        `json:"pageNo"`
	PageSize int                        `json:"pageSize"`
}

func GetWorkOvertimeApprovalPaging(pagination dto.Pagination, name string, userId uint, from string) (WorkOvertimeApprovalPageModel, error) {
	user := GetUserById(userId)
	role := GetRoleById(user.RoleID)
	result := WorkOvertimeApprovalPageModel{
		Total:    0,
		Result:   make([]WorkOvertimeApprovalName, 0),
		PageNo:   pagination.PageNo,
		PageSize: pagination.PageSize,
	}
	offset := (pagination.PageNo - 1) * pagination.PageSize

	dbs := GetInstance().Select("approval_work_overtime.*,concat(IFNULL(user.name,''),'(',user.nick_name,')') as user_name").Joins("left join user on approval_work_overtime.create_by = user.id")
	if from == "1" && role.Code == "small_captain" {
		dbs = dbs.Where("user.dept_id=?", user.DeptID).Where("approval_work_overtime.approval_status='3'").Order("approval_work_overtime.created_at desc")
	} else {
		if role.Code == "supper" {
			dbs = dbs.Where("approval_work_overtime.approval_status!='3'").Order("approval_work_overtime.created_at desc")
		} else {
			dbs = dbs.Where("approval_work_overtime.create_by = ?", userId).Order("approval_work_overtime.created_at desc")
		}
	}

	if err := dbs.Offset(offset).Limit(pagination.PageSize).Find(&result.Result).Error; err != nil {
		return result, err
	}
	if err := dbs.Offset(-1).Limit(-1).Count(&result.Total).Error; err != nil {
		return result, err
	}
	return result, nil
}

func GetWorkOvertimeApproval(p map[string]interface{}, extra ...interface{}) (WorkOvertimeApproval, error, string) {
	f := WorkOvertimeApproval{}
	queryDb := GetInstance().Where(p).First(&f)
	if len(extra) > 0 {
		queryDb = queryDb.Where(extra)
	}
	err := queryDb.Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return f, errors.New("查无记录"), "0"
		}
		return f, errors.New(err.Error()), "1"
	}
	return f, nil, "2"
}

func CreateWorkOvertimeApproval(p WorkOvertimeApproval, userId string) (WorkOvertimeApproval, error) {
	approval := p.ApprovalStatus
	if p.OrderStatus == "2" {
		user := GetUserById(cast.ToUint(userId))
		isCaptain := HasSmallCaptain(user.DeptID)
		if isCaptain {
			approval = "3"
		}
	}
	d := WorkOvertimeApproval{
		UserID:           p.UserID,
		WorkOvertimeTime: p.WorkOvertimeTime,
		Duration:         p.Duration,
		Reason:           p.Reason,
		CreateBy:         userId,
		Remark:           p.Remark,
		OrderStatus:      p.OrderStatus,
		ApprovalStatus:   approval,
		RefuseReason:     p.RefuseReason,
	}
	if err := GetInstance().Create(&d).Error; err != nil {
		return d, errors.New("创建失败")
	}
	return d, nil
}

func UpdateWorkOvertimeApproval(id uint, p WorkOvertimeApproval, user string) (WorkOvertimeApproval, error) {
	f := WorkOvertimeApproval{
		AppModel: AppModel{
			ID: id,
		},
	}
	err := GetInstance().Model(&f).Updates(WorkOvertimeApproval{
		UserID:           p.UserID,
		WorkOvertimeTime: p.WorkOvertimeTime,
		Duration:         p.Duration,
		Reason:           p.Reason,
		UpdateBy:         user,
		Remark:           p.Remark,
		OrderStatus:      p.OrderStatus,
		ApprovalStatus:   p.ApprovalStatus,
		RefuseReason:     p.RefuseReason,
	}).Updates(map[string]interface{}{
		"id": id,
	}).Scan(&f).Error
	if err != nil {
		return f, err
	}
	return f, nil
}

func DeleteWorkOvertimeApproval(id uint) (WorkOvertimeApproval, error) {
	f := WorkOvertimeApproval{}
	err := GetInstance().Unscoped().Where("id = ?", id).Delete(&f).Error
	if err != nil {
		return f, err
	}
	return f, nil
}

func UpdateWorkOvertimeApprovalOrderStatus(id uint, status string, userId uint) (WorkOvertimeApproval, error) {

	approval := ""
	if status == "2" {
		user := GetUserById(userId)
		isCaptain := HasSmallCaptain(user.DeptID)
		if isCaptain {
			approval = "3"
		}
	}

	f := WorkOvertimeApproval{
		AppModel: AppModel{
			ID: id,
		},
	}
	err := GetInstance().Model(&f).Updates(map[string]interface{}{
		"order_status":    status,
		"approval_status": approval,
	}).Scan(&f).Error
	if err != nil {
		return f, err
	}
	return f, nil
}

func UpdateWorkOvertimeApprovalApprovalStatus(p dto.ApprovalRequest, id uint) (WorkOvertimeApproval, error) {
	f := WorkOvertimeApproval{
		AppModel: AppModel{
			ID: id,
		},
	}
	err := GetInstance().Model(&f).Updates(map[string]interface{}{
		"refuse_reason":   p.RefuseReason,
		"approval_status": p.ApprovalStatus,
	}).Scan(&f).Error
	if err != nil {
		return f, err
	}
	return f, nil
}
